﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace Projektarbete
{
    delegate void TriggerAddToPlayerInventory(Item item);
    delegate void TiggerHurtPlayer(ushort amount);

    static class Global
    {
        // Här kan vi lägga saker som måste/borde vara globala över hela projektet
        static SpriteFont basicFont;
        static Texture2D spritesheet;
        static Texture2D playersheet;
        static Texture2D mainHUD;
        static Texture2D inventoryHUD;
        static Texture2D chestHUD;

        static Texture2D potterSheet;
        static Texture2D itemEmpty;
        static Texture2D itemPotionBrown;
        static Texture2D itemPotionGreen;
        static Texture2D itemPotionPink;

        static Texture2D white;


        //TODO: ERSÄTT MED LOADTEXTURE2D()
        public static SpriteFont BasicFont { get { return basicFont; } }
        public static Texture2D Spritesheet { get { return spritesheet; } }
        public static Texture2D Playersheet { get { return playersheet; } }
        public static Texture2D MainHUD { get { return mainHUD; } }
        public static Texture2D InventoryHUD { get { return inventoryHUD; } }
        public static Texture2D ChestHUD { get { return chestHUD; } }

        public static Texture2D PotterSheet { get { return potterSheet; } }
        public static Texture2D ItemEmpty { get { return itemEmpty; } }
        public static Texture2D ItemPotionBrown { get { return itemPotionBrown; } }
        public static Texture2D ItemPotionGreen { get { return itemPotionGreen; } }
        public static Texture2D ItemPotionPink { get { return itemPotionPink; } }

        public static Texture2D White { get { return white; } }

        private static ContentManager contentManager;

        public static Random random;

        static Microsoft.Xna.Framework.Input.Keys[] keyConfig;
        public static Microsoft.Xna.Framework.Input.Keys[] KeyConfig { get { return keyConfig; } }

        public static void Initialize(Microsoft.Xna.Framework.Input.Keys[] playerKeyConfig) // körs när projektet körs, Game1.cs -> Initialize just nu
        {
            Collision.interactionDictionary = new Dictionary<ushort, bool>();

            keyConfig = playerKeyConfig;

            /*
             * 0 = tom
             * 1 = vägg
             * 2 = stängd dörr
             * 3 = öppen dörr
             * 4 = kista
            */
            Collision.interactionDictionary.Add(0, false);
            Collision.interactionDictionary.Add(1, false);
            Collision.interactionDictionary.Add(2, true);
            Collision.interactionDictionary.Add(3, true);
            Collision.interactionDictionary.Add(4, true);

            random = new Random();
        }

        public static void LoadContent(ContentManager Content) // Körs när LoadContent körs
        {
            contentManager = Content;

            basicFont = Content.Load<SpriteFont>("Fonts/basicfont");
            spritesheet = Content.Load<Texture2D>("Tilesheets/terrain");
            playersheet = Content.Load<Texture2D>("Players/player");
            mainHUD = Content.Load<Texture2D>("HUD/mainHUD");
            inventoryHUD = Content.Load<Texture2D>("HUD/inventoryHUD");
            chestHUD = Content.Load<Texture2D>("HUD/chestHUD");

            potterSheet = Content.Load<Texture2D>("Tilesheets/Merchants/merchant");
            itemEmpty = Content.Load<Texture2D>("Items/Empty");
            itemPotionBrown = Content.Load<Texture2D>("Items/Potions/Brown");
            itemPotionGreen = Content.Load<Texture2D>("Items/Potions/Green");
            itemPotionPink = Content.Load<Texture2D>("Items/Potions/Pink");

            white = Content.Load<Texture2D>("white");
        }

        public static Texture2D LoadTexture2D(string path)
        {
            return contentManager.Load<Texture2D>(path);
        }

        public static SpriteFont LoadSpriteFont(string path)
        {
            return contentManager.Load<SpriteFont>(path);
        }

        public static string TrimString(SpriteFont spriteFont, int maxLength, string stringToTrim)
        {
            string returnString = string.Empty;

            if (spriteFont.MeasureString(stringToTrim).X > maxLength)
            {
                string[] splitString = stringToTrim.Split(' ');

                int previousLength = 0;

                foreach (string word in splitString)
                {
                    if (previousLength + spriteFont.MeasureString(word + " ").X > maxLength)
                    {
                        if (previousLength + spriteFont.MeasureString(word).X <= maxLength)
                        {
                            returnString += word;
                        }
                        else
                        {
                            previousLength = 0;
                            returnString += "\n" + word + " ";
                        }
                        previousLength += (int)spriteFont.MeasureString(word + " ").X;
                    }
                    else
                    {
                        previousLength += (int)spriteFont.MeasureString(word + " ").X;
                        returnString += word + " ";
                    }
                }
            }
            else
                return stringToTrim;

            return returnString;
        }

        public static Item[][] GetLinkedListToInventoryArray(LinkedList<Item> list)
        {
            int amountOfRows = 16;

            int columns = (int)Math.Floor((double)(list.Count / amountOfRows)) + 1;

            Item[][] returnArray;

            if (columns < 8)
            {
                columns = 8;

                List<Item> tempList = list.ToList();

                returnArray = new Item[columns][];

                for (int x = 0; x < columns; x++)
                {
                    returnArray[x] = new Item[amountOfRows];
                }

                int indexX = 0;
                int indexY = 0;

                foreach (Item item in list)
                {
                    returnArray[indexY][indexX] = item;

                    indexX++;

                    if (indexX > amountOfRows - 1)
                    {
                        indexY++;
                        indexX = 0;
                    }
                }

                for (int y = 0; y < columns; y++)
                {
                    for (int x = 0; x < amountOfRows; x++)
                    {
                        if (returnArray[y][x] == null)
                            returnArray[y][x] = new ItemPresets.EmptySlot();
                    }
                }
            }
            else
            {
                returnArray = new Item[columns][];

                for (int x = 0; x < columns; x++)
                {
                    returnArray[x] = new Item[amountOfRows];
                }

                int currentColumn = 0;
                int currentIteration = 0;

                foreach (Item item in list)
                {
                    returnArray[currentColumn][currentIteration] = item;

                    currentIteration++;

                    if (currentIteration > amountOfRows - 1)
                    {
                        currentColumn++;
                        currentIteration = 0;
                    }
                }

                for (int y = 0; y < columns; y++)
                {
                    for (int x = 0; x < amountOfRows; x++)
                    {
                        if (returnArray[y][x] == null)
                            returnArray[y][x] = new ItemPresets.EmptySlot();
                    }
                }
            }

            return returnArray;
        }

        public static Item[][] GetLinkedListToChestArray(LinkedList<Item> list)
        {
            int amountOfRows = 7;

            int columns = (int)Math.Floor((double)(list.Count / amountOfRows)) + 1;

            Item[][] returnArray;
            
            if (columns < 8)
            {
                columns = 8;

                List<Item> tempList = list.ToList();

                returnArray = new Item[columns][];

                for (int x = 0; x < columns; x++)
                {
                    returnArray[x] = new Item[amountOfRows];
                }

                int indexX = 0;
                int indexY = 0;
                
                foreach (Item item in list)
                {
                    returnArray[indexY][indexX] = item;

                    indexX++;

                    if (indexX > amountOfRows - 1)
                    {
                        indexY++;
                        indexX = 0;
                    }
                }

                for (int y = 0; y < columns; y++)
                {
                    for (int x = 0; x < amountOfRows; x++)
                    {
                        if (returnArray[y][x] == null)
                            returnArray[y][x] = new ItemPresets.EmptySlot();
                    }
                }
            }
            else
            {
                returnArray = new Item[columns][];

                for (int x = 0; x < columns; x++)
                {
                    returnArray[x] = new Item[amountOfRows];
                }

                int currentColumn = 0;
                int currentIteration = 0;

                foreach (Item item in list)
                {
                    returnArray[currentColumn][currentIteration] = item;

                    currentIteration++;

                    if (currentIteration > amountOfRows - 1)
                    {
                        currentColumn++;
                        currentIteration = 0;
                    }
                }

                for (int y = 0; y < columns; y++)
                {
                    for (int x = 0; x < amountOfRows; x++)
                    {
                        if (returnArray[y][x] == null)
                            returnArray[y][x] = new ItemPresets.EmptySlot();
                    }
                }
            }

            return returnArray;
        }

        /// <summary>
        /// Checks if the player can see the given point
        /// </summary>
        /// <param name="position">position IN TILE FORMAT</param>
        /// <returns></returns>
        public static bool CanPlayerSee(Point position)
        {
            if (MapHandler.lightMap[position.Y][position.X] > 0)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Checks if the player can see the given point
        /// </summary>
        /// <param name="position">position IN TILE FORMAT</param>
        /// <returns></returns>
        public static bool CanPlayerSee(Vector2 position)
        {
            if (MapHandler.lightMap[(int)position.Y][(int)position.X] == 1)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Checks if the player can see the given point
        /// </summary>
        /// <param name="x">x position IN TILE FORMAT</param>
        /// <param name="y">y position IN TILE FORMAT</param>
        /// <returns></returns>
        public static bool CanPlayerSee(int x, int y)
        {
            if (MapHandler.lightMap[y][x] == 1)
            {
                return true;
            }

            return false;
        }

        public static Point ToTilePosition(Point point)
        {
            return new Point((int)Math.Floor(point.X / 24f), (int)Math.Floor(point.Y / 24f));
        }

        public static Point ToTilePosition(Vector2 point)
        {
            return new Point((int)Math.Floor(point.X / 24), (int)Math.Floor(point.Y / 24));
        }

        public static Point ToTilePosition(float x, float y)
        {
            return new Point((int)Math.Floor(x / 24), (int)Math.Floor(y / 24));
        }

        public static Point ToTilePosition(int x, int y)
        {
            return new Point((int)Math.Floor(x / 24f), (int)Math.Floor(y / 24f));
        }
    }
}